#
# format2html-lib.pl
#
# Copyright 1996-2002, Silicon Graphics, Inc.
# All Rights Reserved.
#
# This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
# the contents of this file may not be disclosed to third parties, copied or
# duplicated in any form, in whole or in part, without the prior written
# permission of Silicon Graphics, Inc.
#
# RESTRICTED RIGHTS LEGEND:
# Use, duplication or disclosure by the Government is subject to restrictions
# as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
# and Computer Software clause at DFARS 252.227-7013, and/or in similar or
# successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
# rights reserved under the Copyright Laws of the United States.
#
# requires perl5
#

$_bPreBody = "<P>\n<PRE style=\"margin-left: 8px\">\n";
$_ePreBody = "\n</PRE>\n</P>\n";

my($copyWriteComment) = "\n<!-- 
Copyright 1996-2002 Silicon Graphics, Inc.
ALL RIGHTS RESERVED

UNPUBLISHED:  Rights reserved under the copyright laws of the United
States.   Use of a copyright notice is precautionary only and does not
imply publication or disclosure.

U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND:
Use, duplication or disclosure by the Government is subject to restrictions
as set forth in FAR 52.227.19(c)(2) or subparagraph (c)(1)(ii) of the Rights
in Technical Data and Computer Software clause at DFARS 252.227-7013 and/or
in similar or successor clauses in the FAR, or the DOD or NASA FAR
Supplement.  Contractor/manufacturer is Silicon Graphics, Inc.,
2011 N. Shoreline Blvd. Mountain View, CA 94039-7311.
THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY
INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION,
DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY
PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON
GRAPHICS, INC.
-->";

my($DEBUG, $HIT_COUNT) = 0;
my(@HIT_EXPRS, @TAG_EXPRS) = ();
my(@stop_words) = ("the", "of", "to", "and", "in", "on", "are", "for",
                   "by", "as", "be",  "or", "off", "an",  "if", "but",
                   "is", "it");


#######################################################################
#
# void HTMLHeaderFormat(String $buf)
#
#######################################################################

sub HTMLHeaderFormat{

    my($title) = @_;
    my($prefix) = $_DB;

    if($_DB eq "relnotes"){
       $prefix="relnote";
    }
    my($collection) = $ENV{'COLLECTION'};
    my($os) = "";
    $os = "[".(split(';', $collection))[1]."] " if ($collection ne "");

    if($ENV{'NOHDR'} ne '1') {

       print "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n",
             "<!-- SGI ${prefix}2html VERSION 4.0 -->\n" , 
             "<HTML>\n<HEAD>\n<TITLE>${os}${title}</TITLE>\n</HEAD>\n",
             "<BODY BGCOLOR=\"#f9f9f9\">\n";
    }

    print "$copyWriteComment\n\n", $_bPreBody;
    return;
}


#######################################################################
#
# void HTMLTrailerFormat(void)
#
#######################################################################

sub HTMLTrailerFormat{

    print $_ePreBody;
    if($ENV{'NOHDR'} ne '1') {
       print "\n</BODY>\n</HTML>\n";
    }
    return;
}


#######################################################################
#
# void addLinks(String_ref \$buf)
#
#######################################################################

sub addLinks{

    my($buf_ref) = @_;
    my($script_name) = $ENV{'SCRIPT_NAME'} || "/cgi-bin/infosrch.cgi";
    my($collection)  = $ENV{'COLLECTION'};
    my($coll) = "";
    $coll = (split(';', $collection))[0] if ($collection ne "");
    my($cgi) = "$script_name\?cmd=getdoc&coll=$coll&db=man&fname=";
    my($tag)="<[^>]+>";
    
    # Add_disk in fx(1) is broken.
    # Try to make this simplier & cleaner, but measure performance 

    # Match command(1M) and make it a hyperlink to 
    $$buf_ref =~ s/<B>([\w.\-_]+)<\/B>\(([1-8])[a-zA-Z]{0,2}\)/<A HREF="$cgi$2%20$1">$&<\/A>/go;

    $$buf_ref =~ s/<B><TT>([\w.\-_]+)<\/TT><\/B>\(([1-8])[a-zA-Z]{0,2}\)/<A HREF="$cgi$2%20$1">$&<\/A>/go;

    $$buf_ref =~ s/<I>([\w.\-_]+)<\/I>\(([1-8])[a-zA-Z]{0,2}\)/<A HREF="$cgi$2%20$1">$&<\/A>/go;

    $$buf_ref =~ s/<I>([\w.\-_]+)<\/I>\(<I>([1-8])[a-zA-Z]{0,2}<\/I>\)/<A HREF="$cgi$2%20$1">$&<\/A>/go;

    $$buf_ref =~ s/([\w.\-_]+)\(([1-8])[a-zA-Z]{0,2}\)/<A HREF="$cgi$2%20$1">$&<\/A>/go;

    ## $$buf_ref =~ s/($tag*\#include$tag*\s+$tag*\&lt\;)(\S+)(\&gt\;$tag*)/$1<A HREF=\"file:\/usr\/include\/$2\">$2<\/A>$3/go;

    # This fixes non-highlight #includes (Cosmo's csAction)
    # Fix $tag above to deal with both.  
    # This is a bit tricky, since we're grabbing
    # $2 & $3 and if we add more ()'s it'll throw if off. 
    #
    ## $$buf_ref =~ s/(\#include\s+\&lt\;)(\S+)(\&gt\;)/$1<A HREF=\"file:\/usr\/include\/$2\">$2<\/A>$3/go;

    ## $$buf_ref =~ s/(<B><TT>\&lt\;)(\S+)(\.h\&gt\;<\/TT><\/B>)/<B><TT>\&lt\;<A HREF=\"file:\/usr\/include\/$2\.h\">$2\.h<\/A>\&gt\;<\/TT><\/B>/go;
}



#######################################################################
#
# void removeHTMLTags(String_ref \$buf)
#
#######################################################################

sub removeHTMLTags {
    my($buf_ref) = @_;
    $$buf_ref =~ s/<[^>]*>//g;
}


#######################################################################
#
# int findIndent(String_ref \$buf,int tabsize)
#
#######################################################################

sub findIndent{

    my($buf_ref,$tabsize) = @_;

    my($isIndent) = 1;  
    my($indent) = 0;   
    my($c) = 0;

    while($isIndent == 1){
    	
	if (substr($$buf_ref, $c, 1) eq " " ){
	    $indent++;
	}
        elsif (substr($$buf_ref, $c, 1) eq "\t" ){
	    $indent = $indent + $tabsize;
	}
	else{
	    $isIndent=0;
	}
	$c++;
    }
   
    return($indent);
}


#######################################################################
#
# int hasInternalSpace(String_ref \$buf)
#
# return the number of "gaps" found.  Don't count ".  " as a gap.
#
#######################################################################

sub hasInternalSpace{

    my $buf_ref = shift;

    # Don't match ".  " or ".)  " or ":  " or "\n  "
    # Or ".</TAG>  ", etc.

    $line = $$buf_ref;
    $line =~ (s/  / /g);
    my @spaces = ($line =~ m/[^\.\ \n\,\;\:>\)](<\/[A-Z]{1,5}>)*\ {2,}\S/g);

    $i = @spaces;
    if( $i == 0 ) {
        # this looks for something that begins with a tag and a pound-sign
        # used esp. in release notes, ditto for the percent sign
        @spaces = ($line =~ m/([\ ]+<[A-z]>)[#%]/);
    }

    return($#spaces+1);
}


#######################################################################
#
# void bigFormat(String $buf)
#
#######################################################################

sub bigFormat{
    my($buf) = @_;
    print "<BIG><B>", $buf, "</B></BIG>\n\n";
}


#######################################################################
#
# void pageBreakRemoval(String_ref $buf)
#
# Look at each "---PAGE BREAK---" and 
#
#######################################################################

sub pageBreakRemoval{

    my($buf_ref) = @_;
    my($pos,$preline_pos,$postline_post) = 0;
    my($preline,$postline) = "";
    my($preindent,$postindent) = "";
    my($true)  = 1;
    my($false) = 0;
    my($merge) = $false;
    my($subsystemline) = 
	"^\s+(<I>[^<]+<\/I>)\.?){3}\ {3,}";

    # Page 1 break, with no preceding paragraph
    $$buf_ref=~s/^\n*---PAGE\ BREAK---\n//;

    while(($pos=index($$buf_ref,"\n---PAGE BREAK---\n")) >= 0 ){

	$preindent = 0;
	$postindent = 0;  # What if lines aren't found?

	if(($preline_pos = rindex($$buf_ref,"\n",$pos-1)) >= 0){
	    $preline = substr($$buf_ref,$preline_pos+1,($pos-$preline_pos-1));
	    #print STDERR "$preline\n";
	    $preindent  = &findIndent(\$preline,$tab);
	}else{
	    print STDERR "Missed preline\n"
		unless($DEBUG==0);
	}

	if(($postline_pos = index($$buf_ref,"\n",$pos+18)) >= 0){
	    $postline = substr($$buf_ref,$pos+18,($postline_pos-($pos+18)));
	    #print STDERR "$postline\n";
	    $postindent = &findIndent(\$postline,$tab); 
	}else{
	    print STDERR "Missed postline\n"
		unless($DEBUG==0);
	}
 	
	# Assert of preindent or post = 0;

	# Merge pagebreaks in relnotes tables

	if($preline=~/^\s+(<I>[^<]+<\/I>\.?){3}\ {3,}/ 
	    && $_DB ne "man"){ 
	    $merge = $true;
	}elsif($postline=~/^\s+(<I>[^<]+<\/I>\.?){3}\ {3,}/ 
	       && $_DB ne "man"){
	    $merge = $true;    
	}elsif($preindent != $postindent){ # Split paragraphs  
		$merge = $false;
	}else{  # Same level - merge into 1 paragraph?

	    # If preline & post line have the same number of gaps,
	    # it's probably a table we need to merge.
	    my $prespaces = &hasInternalSpace(\$preline);

	    if(($prespaces > 1) && 
	       ($prespaces == &hasInternalSpace(\$postline))){
		$merge = $true; # Merge to sections of a table
	    }else{
		
		# Does preline end in a period? (Followed by </B> or &gt;)
		# Broken in serial(7)
		if($preline=~/\.(<\/[BIT]{1,2}>){0,2}?$/){
		    $merge = $false; 
		}else{
		    if($postline=~/^\s+((\d)|(\x8o)|(-))/){ # Start list
			$merge = $false;
		    }else{
			$merge = $true;
		    }
		}
	    }
	}

	if($merge == $true){
	    $$buf_ref =~ s/---PAGE\ BREAK---\n//;
	}else{
	    $$buf_ref =~ s/---PAGE\ BREAK---//;
	}
	$pos++;
        $pos=index($$buf_ref,"\n---PAGE BREAK---\n");
    } 

    return;
}


#######################################################################
#
# void outputHTMLPage(String $buf)
#
# Ungzip & filter page thru ss2nonss if needed 
#
#######################################################################

sub outputHTMLPage {

    my $gzfile = shift;

    my($ss2nonss) = "./ss2nonss";
    my($script_name) = $ENV{'SCRIPT_NAME'} || "/cgi-bin/infosrch.cgi";
    my($collection)  = $ENV{'COLLECTION'};
    my($coll) = "";
    $coll = (split(';', $collection))[0] if ($collection ne "");

    my($j)=0;
    my($s,$cgi,$tmp) = '';
    $cgi = "$script_name\?coll=$coll&";

    # Test the browser-type to determine if it can 
    # handle stylesheets.  If it can't, pass it thru
    # ss2nonss.  For now, assume all are non-compliant            

    my($cmd) = "gunzip -dc $gzfile | $ss2nonss";

    open(CMD, "$cmd |") || die "$cmd: !$\n";
    while (<CMD>) {

           if($_ =~ /infosrch\.cgi\?/) {
              $s = $_;
              if( $s =~ /fname=http:/ ) {
                  $j = index($s, "=http:");
                  $tmp = substr($s, $j+1);

                  $s = substr($s, 0, $j);
                  $s =~ s/\/cgi\-bin\/infosrch\.cgi\?/$cgi/g;

                  $tmp =~ s/\/(\w+)\/books\/(\w+)\///;
                  $s .= "=/$1/$2";
                  $j = index($tmp, "\"");
                  $tmp = substr($tmp, $j);
                  $s .= $tmp;
              } else {
                  $s =~ s/\/cgi\-bin\/infosrch\.cgi\?/$cgi/g;
              }
              print $s;
           } else {
              print $_;
           }
    }
    close(CMD);
}


#######################################################################
#
# hilite(buf)
#
# Hilite keywords in HTML
#
#######################################################################

sub hilite {

    my($buf) = @_;

    my($pat1, $pat2, $c) = '';
    my($i, $j, $len_tag, $len_hit) = 0;
    my($hit_word) = "<A NAME=\"darkred1\"></A>";

    $len_hit = (@HIT_EXPRS + 0);
    $len_tag = (@TAG_EXPRS + 0);
    if ($len_hit == 0 && $len_tag == 0) {
         return;
    }
   

    # split tags and content
    #
    my(@chunks) = split(/(<[^>]+?>)/, $$buf);

    $$buf = '';
    foreach $c (@chunks) {

        # highlight content; outside of tags (\b is word boundary)
        #
        if ($c !~ m#^<#) {

            for ($i=0; $i < $len_hit; $i++) {

              $pat1 = $HIT_EXPRS[$i];

              # patch for c++; anything followed by "++"
              #
              if ($pat1 =~ /ZzZz/ ) {

                  $pat1 =~ s/ZzZz//;
                  $c =~ s/\b(${pat1}[\+]{2})([\W]+)/<FONT COLOR=\"darkred\"><B style=\"color:darkred;background-color:#cccccc\">$1<\/B><\/FONT>$2/gi;

              } elsif ($c =~ s/\b($pat1)\b/<FONT COLOR=\"darkred\"><B style=\"color:darkred;background-color:#cccccc\">$1<\/B><\/FONT>/gi) {

                   # once for 1st hit; must be global - some docs in chunks
                   #
                   if ($HIT_COUNT == 0) {
                       $c =~ s/(${pat1}<\/B>){1}/${hit_word}${1}/i;
                       $HIT_COUNT = 1;
                   }
              }
            }

        } else {

            # modify inside tags
            #
            for ($i=0, $j=0; $i < $len_tag; $i++) {

                 if (($j = ($i+1)) < $len_tag) {
                      $pat1 = ${TAG_EXPRS}[$i];
                      $pat2 = ${TAG_EXPRS}[$j];
                      $c =~ s/${pat1}/${pat2}/gi;
                      $i++;
                 }
            }
        }

        $$buf .= $c;
    }
}


#######################################################################
#
# buildExpression(srch_str)
#
# build array to use to hilite kywrds
#
#######################################################################

sub buildExpression {

    my($in_str) = @_;

    @HIT_EXPRS = ();
    $HIT_COUNT = 0;

    if ($in_str eq '') {
        return;
    }
 
    $in_str =~ s/^[^\w\/]+//g;
    $in_str =~ s/\+\+/ZzZz/g;
    $in_str =~ s/[^\w\/\*]+$//g;
    $in_str =~ s/[^\w\/\:\_\-\*\.]/ /g;

    my(@wrds) = split(' ', $in_str);

    my($wildcard) = "[^\ \.<]*";
    my($s) = '';
    my($add) = 0;

    foreach $s (@wrds) {

        $s =~ s/^[^\w\/]+//g;
        $s =~ s/[^\w\/\*]+$//g;

        if ($s !~ /[\w]{2,}/) {
            next;
        }

        $add = 1;
        foreach (@stop_words) {
           if ($s =~ /^${_}$/i) {
               $add = 0;
               last;
           }
        }

        if ($add == 0) {
            next;
        }

        $s =~ s/\*/${wildcard}/g;
        push(@HIT_EXPRS, $s);
    }

    return;
}


sub addTagExpression {

    my($expr1, $expr2) = @_;
    if ($expr1 ne '') {
        push(@TAG_EXPRS, $expr1);
        push(@TAG_EXPRS, $expr2);
    }
}


#
# {un}escape(string s)
#
# escape a string for use in a URL
#
sub unescape {
  my($todecode) = @_;
  $toencode =~ s/%20/\ /g;
  $toencode =~ s/%22/\"/g;
  $toencode =~ s/%26/\&/g;
  $toencode =~ s/%27/\'/g;
  $toencode =~ s/%2B/\+/g;
  $toencode =~ s/%2F/\//g;
  return $todecode;
}

sub escape {
  my($toencode) = @_;
  $toencode =~ s/\ /%20/g;
  $toencode =~ s/\+/%2B/g;
  $toencode =~ s/\"/%22/g;
  $toencode =~ s/\&/%26/g;
  $toencode =~ s/\'/%27/g;
  return $toencode;
}


# Return true from package include
#
1;

